;;;; Apple Plist file reader/writer
;;;; Heehong Moon <bbirec@gmail.com>

(defpackage :cl-plist
  (:use :common-lisp)
  (:export
   
   :decode-plist
   :decode-plist-from-stream))

(in-package :cl-plist)


(defun decode-plist (filepath)
  (with-open-file (s filepath)
    (decode-plist-from-stream s)))

(defun decode-plist-from-stream (stream)
  (let ((sexp (caddr (xmls:parse stream))))
    (decode-top-level sexp)))


(defmacro string-or (str strings &rest body)
  `(cond 
     ,@(loop for s in strings collect
	    `((string= ,str ,s) ,@body))))


(defmacro string-cond (str &rest args)
  `(cond
     ,@(loop for (s f) in args
	 if (= (length s) 1) collect `((string= ,str ,@s) ,f)
	    else collect `((string-or ,str ,s) ,f))))
	    
	    
(defun decode-top-level (sexp)
  (let ((name (car sexp))
	(rest (cddr sexp))
	(value (caddr sexp)))
    (string-cond name
		 (("dict") (decode-dict rest))
		 (("array") (decode-array rest))
		 (("string") value)
		 (("date") (decode-date value))
		 (("data") (decode-data value))
		 (("true" "false") (decode-bool name))
		 (("integer" "real") (decode-value value)))))

	   

(defun decode-dict (sexp)
  (let ((alist nil)
	(h (make-hash-table)))
    (loop for i from 0 below (length sexp) by 2 do
	 (let* ((key (caddr (nth i sexp)))
		(value (decode-top-level (nth (1+ i) sexp)))
		(keyw (intern key :keyword)))
	   (setf alist (acons keyw value alist))
	   (setf (gethash keyw h) value)))
    h))
	    


(defun decode-array (sexp)
  (loop for i in sexp collect (decode-top-level i)))

(defun decode-bool (str)
  (if (equal str "true") t nil))

(defun decode-value (str) 
  (unless (null str) (read-from-string str)))

(defun decode-date (str)
  "Not implemented"
  str)

(defun decode-data (str)
  "Not implemented"
  str)